/**
 * @filename		AlertService.java
 * @author			dhy
 * @date			2016年7月04日-下午2:20:02
 * @description	AlertService
 */
package com.android.functionmanagement.service;

import android.app.Dialog;
import android.app.Instrumentation;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.widget.TextView;

import com.android.functionmanagement.globle.ConstantGloble;
import com.android.functionmanagement.location.LocationGpsService;
import com.android.functionmanagement.ui.AlertManometrySettings;
import com.android.functionmanagement.ui.AlertPharmacySettings;
import com.android.functionmanagement.util.AlarmManagerUtil;
import com.android.functionmanagement.util.HeartRateUtils;
import com.android.functionmanagement.util.JSONUtil;
import com.android.functionmanagement.util.SharedPreferencesUtils;
import com.uwatch.helowin.R;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;

import org.json.JSONException;

/**
 * @author dhy
 */

public class AlertService extends Service {

	private final static int MSG_CANCEL_RING = 0x1000;
	private final static int MSG_CANCEL_ALERT_WINDOW = 0x1001;
	private boolean mPhEnableRing;
	private boolean mPhEnableVibrate;
	private String mPhTime = "";
//	private String[] mPhDays;

	private boolean mMoEnableRing;
	private boolean mMoEnableVibrate;
	private String mMaTime = "";
	private String mMaPeriod = "0";
	private String[] mMaDays = {};
	private HashMap<String, String> mMeds = new HashMap<String, String>();

	private WakeLock mWakeLock ;
	private Handler mHandler = new Handler() {
		@Override
		public void dispatchMessage(Message msg) {

			switch (msg.what) {
			case MSG_CANCEL_RING:
				Ringtone ring = (Ringtone) msg.obj;
				ring.stop();
				break;
			case MSG_CANCEL_ALERT_WINDOW:
				Dialog dlg = (Dialog) msg.obj;
				if (dlg != null && dlg.isShowing())
					dlg.dismiss();
				break;
			default:
				break;
			}
		};
	};

	private OnSharedPreferenceChangeListener mChangeListener = new OnSharedPreferenceChangeListener() {

		@Override
		public void onSharedPreferenceChanged(
				SharedPreferences sharedPreferences, String key) {
			// TODO Auto-generated method stub
			// AlertManometry
			boolean phEnable = mPhEnableRing || mPhEnableVibrate;
			boolean maEnable = mMoEnableRing || mMoEnableVibrate;
			if (AlertManometrySettings.MA_RING_ONOFF.equals(key)) {
				mMoEnableRing = sharedPreferences
						.getBoolean(key, mMoEnableRing);
			} else if (AlertManometrySettings.MA_VIBRATE_ONOFF.equals(key)) {
				mMoEnableVibrate = sharedPreferences.getBoolean(key,
						mMoEnableVibrate);
			} else if (AlertManometrySettings.MA_TIME_PICK.equals(key)) {
				if (maEnable) {
					enableMaAlarm(false);
					maEnable = !maEnable;
				}
				mMaTime = sharedPreferences.getString(key, mMaTime);
			} else if (AlertManometrySettings.MA_DAY_PICK.equals(key)) {
				if (maEnable) {
					enableMaAlarm(false);
					maEnable = !maEnable;
				}
				Set<String> values = sharedPreferences.getStringSet(key, null);
				if (values != null)
					mMaDays = values.toArray(new String[] {});
			}// AlertPharmacy
			else if (AlertPharmacySettings.PH_VIBRATE_ONOFF.equals(key)) {
				mPhEnableVibrate = sharedPreferences.getBoolean(key,
						mPhEnableVibrate);
			} else if (AlertPharmacySettings.PH_RING_ONOFF.equals(key)) {
				mPhEnableRing = sharedPreferences
						.getBoolean(key, mPhEnableRing);
			} else if (AlertPharmacySettings.PH_TIME_PICK.equals(key)) {
				if (phEnable) {
					enablePhAlarm(false);
					phEnable = !phEnable;
				}
				mPhTime = sharedPreferences.getString(key, mPhTime);

			}/* else if (AlertPharmacySettings.PH_DAY_PICK.equals(key)) {
				if (phEnable) {
					enablePhAlarm(false);
					phEnable = !phEnable;
				}
				Set<String> values = sharedPreferences.getStringSet(key, null);
				if (values != null)
					mPhDays = values.toArray(new String[] {});

			}*/

			if (phEnable ^ (mPhEnableRing || mPhEnableVibrate))
				enablePhAlarm(mPhEnableRing || mPhEnableVibrate);

			if (maEnable ^ (mMoEnableRing || mMoEnableVibrate))
				enableMaAlarm(mMoEnableRing || mMoEnableVibrate);
		}
	};

	@Override
	public IBinder onBind(Intent intent) {
		// TODO: Return the communication channel to the service.
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Service#onCreate()
	 */
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		mWakeLock = ((PowerManager) getSystemService(POWER_SERVICE))
		.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getSimpleName());
		mWakeLock.setReferenceCounted(false);
		
		SharedPreferences sh = PreferenceManager
				.getDefaultSharedPreferences(this);

		mPhEnableRing = sh.getBoolean(AlertPharmacySettings.PH_RING_ONOFF,
				getResources().getBoolean(R.bool.def_enable_ph_ring));

		mPhEnableVibrate = sh.getBoolean(
				AlertPharmacySettings.PH_VIBRATE_ONOFF, getResources()
						.getBoolean(R.bool.def_enable_ph_vibrate));

		mMoEnableRing = sh.getBoolean(AlertManometrySettings.MA_RING_ONOFF,
				getResources().getBoolean(R.bool.def_enable_mo_ring));

		mMoEnableVibrate = sh.getBoolean(
				AlertManometrySettings.MA_VIBRATE_ONOFF, getResources()
						.getBoolean(R.bool.def_enable_mo_vibrate));
		mPhTime = sh.getString(AlertPharmacySettings.PH_TIME_PICK,""
				/*getString(R.string.def_ph_time)*/);

		mMaTime = sh.getString(AlertManometrySettings.MA_TIME_PICK,""
				/*getString(R.string.def_ma_time)*/);
		
		Set<String> values = sh.getStringSet(AlertManometrySettings.MA_DAY_PICK, null);
		if (null != values)
//			mMaDays = getResources().getStringArray(R.array.def_ma_day_value);
//		else
			mMaDays = values.toArray(new String[] {});
		
//		values = sh.getStringSet(AlertPharmacySettings.PH_DAY_PICK,
//				null);
//		if (null == values)
//			mPhDays = getResources().getStringArray(R.array.def_ph_day_value);
//		else
//			mPhDays = values.toArray(new String[] {});
		getFamilyNumbers();
		getMaTime();
		getMeds();
		enablePhAlarm(mPhEnableRing || mPhEnableVibrate);
		enableMaAlarm(mMoEnableRing || mMoEnableVibrate);
		sh.registerOnSharedPreferenceChangeListener(mChangeListener);
		LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
		lbm.registerReceiver(mBReceiver, new IntentFilter(
				"com.android.action.GETUSERINFO"));
		TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
	}

	private BroadcastReceiver mBReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) {
			updatePush();
		}
	};
	private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
		/*
		 * (non-Javadoc)
		 * 
		 * @see android.telephony.PhoneStateListener#onCallStateChanged(int,
		 * java.lang.String)
		 */
		@Override
		public void onCallStateChanged(int state, String incomingNumber) {
			// TODO Auto-generated method stub
			switch (state) {
			case TelephonyManager.CALL_STATE_IDLE:
				break;

			case TelephonyManager.CALL_STATE_RINGING:
				boolean sos = (Boolean) SharedPreferencesUtils.getParam(
						AlertService.this, "SOS_ALERT", false);
				//Log.w("DHYCO","sos="+sos+",incomingNumber="+incomingNumber);
				if (null != incomingNumber && sos){
					new Thread() {
						@Override
						public void run() {
							new Instrumentation()
									.sendKeyDownUpSync(KeyEvent.KEYCODE_CALL);
						}
					}.start();
					SharedPreferencesUtils.setParam(
							AlertService.this, "SOS_ALERT", false);
				}
				break;
			case TelephonyManager.CALL_STATE_OFFHOOK:

				break;
			}
		}
	};

	private void updatePush() {
		SharedPreferences sh = PreferenceManager
				.getDefaultSharedPreferences(this);
		Editor ed = sh.edit();
		if ("".equals(SharedPreferencesUtils.getParam(this,
				ConstantGloble.USERID, "").toString())) {
			Log.w("DHYCO","clear alert Alarm");
			enableMaAlarm(false);
			enablePhAlarm(false);
			ed.putString(AlertPharmacySettings.PH_TIME_PICK, "");
			ed.putString(AlertManometrySettings.MA_TIME_PICK, "");
			ed.putStringSet(AlertManometrySettings.MA_DAY_PICK,
					new HashSet<String>());
			ed.commit();
			return;
		}
		getFamilyNumbers();
		getMaTime();
		getMeds();
	}

	@SuppressWarnings("unchecked")
	private void getFamilyNumbers() {
		String dataStrings = SharedPreferencesUtils.getParam(this,
				"numberList", "").toString();
		dataStrings = dataStrings.replace("}, {", "},{").replace("=", "=\"")
				.replace(", ", "\", ").replace("}", "\"}")
				.replace("},{", "}, {");
		try {
			ArrayList<HashMap<String, Object>> datas = (ArrayList<HashMap<String, Object>>) JSONUtil
					.parseJsonResponse(dataStrings);
			if (datas == null)
				return;
			String[] mNumList = new String[datas.size()];
			for (int i = 0; i < mNumList.length; i++) {
				mNumList[i] = "" + datas.get(i).get(ConstantGloble.MOBILE);
			}
			Intent intent = new Intent(this, CallService.class);
			intent.putExtra("NUMBER_LIST", mNumList);
			startService(intent);
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}
	
	private void getMaTime() {
		SharedPreferences sh = PreferenceManager
				.getDefaultSharedPreferences(this);
		Editor ed = sh.edit();
		String[] archives = SharedPreferencesUtils
				.getParam(this, "archive", "").toString().replace("{", "")
				.replace("}", "").split(",");

		String maTime = "";
		String maPeriod = "";
		String[] maDays = mMaDays;
		for (String archive : archives) {
			if (archive.contains("hours=")) {
				String[] maTimes = archive.substring("hours=".length()
						+ archive.indexOf("hours=")).split("\\|");
				for (String time : maTimes) {
					String[] hm = time.split(":");
					String hour = hm.length > 0 ? hm[0] : "";
					String minute = hm.length > 1 ? hm[1] : "";
					if (!"".equals(hour) && hour.length() == 1)
						hour = "0" + hour;
					if (!"".equals(hour) && "".equals(minute))
						minute = "00";
					if (!"".equals(minute) && minute.length() == 1)
						minute = "0" + minute;
					time = hour+":"+minute;
					maTime += time + "|";
				}
			} else if (archive.contains("days=")) {
				maDays = archive
						.substring("days=".length() + archive.indexOf("days="))
						.replaceAll("\\D+", ",").split(",");
			}else if (archive.contains("period=")) {
				maPeriod = archive
						.substring("period=".length() + archive.indexOf("period="));
			}
		}
		Set<String> days = new HashSet<String>();
		Collections.addAll(days, maDays == null ? mMaDays : maDays);
		mMaTime = maTime;
		mMaPeriod = maPeriod;
		ed.putString(AlertManometrySettings.MA_TIME_PICK, maTime);
		ed.putStringSet(AlertManometrySettings.MA_DAY_PICK, days);
		ed.commit();
	}
	
	private void getMeds() {
		SharedPreferences sh = PreferenceManager
				.getDefaultSharedPreferences(this);
		Editor ed = sh.edit();
		String[] medList = SharedPreferencesUtils.getParam(this, "medList", "")
				.toString().replace("{", "").replace("}", "").replace("[", "")
				.replace("]", "").split(", ");
		ArrayList<String> timeList = new ArrayList<String>();
		mMeds.clear();
		SparseArray<String> meds = new SparseArray<String>();
		int i = 0;
		for (String med : medList) {
			String medName = "";
			if (med.contains("medName=")) {
				medName = med.substring("medName=".length()
						+ med.indexOf("medName="));
				meds.put(i++, medName);
			}
		}
		i = 0;
		for (String med : medList) {
			if (med.contains("hours=")) {
				String[] phTime = med.substring(
						"hours=".length() + med.indexOf("hours=")).split("\\|");
				for (String time : phTime) {
					String[] hm = time.split(":");
					String hour = hm.length > 0 ? hm[0] : "";
					String minute = hm.length > 1 ? hm[1] : "";
					if (!"".equals(hour) && hour.length() == 1)
						hour = "0" + hour;
					if (!"".equals(hour) && "".equals(minute))
						minute = "00";
					if (!"".equals(minute) && minute.length() == 1)
						minute = "0" + minute;
					time = hour+":"+minute;
//					Log.i("DHYCO","time="+time);
					if (!timeList.contains(time))
						timeList.add(time);
					String value = mMeds.get(time);
					mMeds.put(time, value == null ? meds.get(i) : value + "\n"
							+ meds.get(i));
				}
				i++;
			}
		}
		Collections.sort(timeList);
//		Log.i("DHYCO","time="+Arrays.toString(timeList.toArray(new String[]{})));
		mPhTime = timeList.toString().replace("{", "").replace("}", "")
				.replace("[", "").replace("]", "").replace(", ", "|");
//		Log.i("DHYCO","mPhTime="+mPhTime);
		ed.putString(AlertPharmacySettings.PH_TIME_PICK, mPhTime);
		ed.commit();
	}
	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Service#onStartCommand(android.content.Intent, int, int)
	 */
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		if (null != intent) {
			int action = intent.getIntExtra(ConstantGloble.ALARMACTION, -1);
			if (action == -1)
				return START_STICKY;
			// long intervalMillis = intent.getLongExtra(
			// ConstantGloble.INTERVAL_MILLIS, 0);
			// if (intervalMillis > 0) {
			// AlarmManagerUtil.setAlarmTime(this, System.currentTimeMillis()
			// + intervalMillis, intent);
			// }
			if (action == ConstantGloble.ALARM_ACTION_ALERT_PH) {
				showAlertWindow(intent,action);
				if (mPhEnableRing) {
					mWakeLock.acquire(13 * 1000);
					Ringtone ring = RingtoneManager.getRingtone(this,
							RingtoneManager
									.getDefaultUri(RingtoneManager.TYPE_ALARM));
					ring.play();
					mHandler.sendMessageDelayed(
							mHandler.obtainMessage(MSG_CANCEL_RING, ring),
							10 * 1000);
				}
				// AlertUtil.getInstance().load(
				// Settings.System.getUriFor(
				// Settings.System.ALARM_ALERT).getPath(), 5,
				// 1);
				if (mPhEnableVibrate) {
					mWakeLock.acquire(13 * 1000);
					Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
					vibrator.vibrate(new long[] { 200, 300, 200, 1000, 300,
							100, 200, 1000, 300, 500, 200, 2000 }, -1);
				}
			} else if (action == ConstantGloble.ALARM_ACTION_ALERT_MO) {
				showAlertWindow(intent,action);
				if (mMoEnableRing) {
					mWakeLock.acquire(13 * 1000);
					Ringtone ring = RingtoneManager.getRingtone(this,
							RingtoneManager
									.getDefaultUri(RingtoneManager.TYPE_ALARM));
					ring.play();
					mHandler.sendMessageDelayed(
							mHandler.obtainMessage(MSG_CANCEL_RING, ring),
							10 * 1000);
				}
				// AlertUtil.getInstance().load(
				// Settings.System.getUriFor(
				// Settings.System.ALARM_ALERT).getPath(), 5,
				// 1);
				if (mMoEnableRing) {
					mWakeLock.acquire(13 * 1000);
					Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
					vibrator.vibrate(new long[] { 200, 300, 200, 1000, 300,
							100, 200, 1000, 300, 500, 200, 2000 }, -1);
				}
			} else if (action == ConstantGloble.SOS_REQUEST_LOCATION) {
				upLoadPush();
			}
		}
		return START_STICKY;
	}

	/**
	 * 
	 * @param intent
	 * @param action
	 */
	private void showAlertWindow(Intent intent, int action) {
		int msgId = R.string.alert_medicine;
		if (action == ConstantGloble.ALARM_ACTION_ALERT_MO)
			msgId = R.string.alert_manometry;
		String alarm_time = intent.getStringExtra("ALARM_TIME");
		Dialog dlg = new Dialog(this);
		dlg.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
		dlg.getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
						| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
						| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
		dlg.setTitle(msgId);
		dlg.setContentView(R.layout.alert_window_layout);
		if (msgId == R.string.alert_medicine)
			((TextView) dlg.findViewById(R.id.alert_text_view)).setText(mMeds
					.get(alarm_time));
		else
			((TextView) dlg.findViewById(R.id.alert_text_view))
					.setText(R.string.alert_manometry);
		dlg.show();
		WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
		Display display = windowManager.getDefaultDisplay();
		WindowManager.LayoutParams lp = dlg.getWindow().getAttributes();
		lp.width = (int) (display.getWidth()); // 设置宽度
		lp.height = (int) (display.getHeight());
		dlg.getWindow().setAttributes(lp);
		mHandler.sendMessageDelayed(
				mHandler.obtainMessage(MSG_CANCEL_ALERT_WINDOW, dlg), 30 * 1000);
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Service#onDestroy()
	 */
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		mWakeLock.release();
		mWakeLock = null;
		PreferenceManager.getDefaultSharedPreferences(this)
				.unregisterOnSharedPreferenceChangeListener(mChangeListener);
		LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
		lbm.unregisterReceiver(mBReceiver);
		TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		tm.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
	}

	/**
	 * 
	 * @param enable
	 */
	private void enableMaAlarm(boolean enable) {
		if (null == mMaTime
				|| (!"0".equals(mMaPeriod) && (null == mMaDays || mMaDays.length == 0))
				|| "".equals(mMaTime))
			return;
		int period = Integer.parseInt(mMaPeriod);
		if (enable) {
			String[] hmt = mMaTime.split("\\|");
			int j = 0;
			for (String time : hmt) {
				String[] hm = time.split(":");
				for (int i = 0; i < (period == 0?1:mMaDays.length); i++) {
					Log.d("DHYCO","hm[0]="+hm[0]+",,,,hm[1]="+hm[1]);
					try {
						AlarmManagerUtil.setAlarm(
								this,
								period+1,
								Integer.parseInt(hm[0]),
								Integer.parseInt(hm[1]),
								ConstantGloble.ALARM_ACTION_ALERT_MO + j *(period == 0?1: i),
								(period == 0 ? 0 : Integer
										.parseInt(mMaDays[i] + 1)),
								ConstantGloble.ALARM_ACTION_ALERT_MO, 2,
								AlertService.class);
					} catch (NumberFormatException e) {
						// TODO: handle exception
					}
				}
				j++;
			}

		} else {
			String[] hmt = mMaTime.split("\\|");
			int all  =  (period == 0?1:mMaDays.length) * hmt.length;
			for (int i = 0; i < all; i++) {
				int ind = (i / all) % hmt.length;
				Log.d("DHYCO", "hmt[" + ind + "]=" + hmt[ind]);
				AlarmManagerUtil.cancelAlarm(this,
						ConstantGloble.ALARM_ACTION_ALERT_MO,
						ConstantGloble.ALARM_ACTION_ALERT_MO + i, 2,
						AlertService.class);
			}
		}
	}

	/**
	 * 
	 * @param enable
	 */
	private void enablePhAlarm(boolean enable) {
		if(mPhTime == null || "".equals(mPhTime))
			return;
		if (enable) {
			String[] times = mPhTime.split("\\|");
			Log.i("DHYCO","times="+Arrays.toString(times));
			for (int i = 0; i < times.length; i++) {
				String[] hm =times[i].split(":");
				try {
					AlarmManagerUtil.setAlarm(this, 1, Integer.parseInt(hm[0]),
							Integer.parseInt(hm[1]),
							ConstantGloble.ALARM_ACTION_ALERT_PH + i, 0,
							ConstantGloble.ALARM_ACTION_ALERT_PH, 2,
							AlertService.class);
				} catch (NumberFormatException e) {
					// TODO: handle exception
				}
			}
		} else {
			String[] times = mPhTime.split("\\|");
			for (int i = 0; i < times.length; i++) {
				Log.i("DHYCO","times["+i+"]="+times[i]);
				AlarmManagerUtil.cancelAlarm(this,
						ConstantGloble.ALARM_ACTION_ALERT_PH,
						ConstantGloble.ALARM_ACTION_ALERT_PH + i, 2,
						AlertService.class);
			}
		}
	}
	
	private void upLoadPush() {
		// TODO Auto-generated method stub
		new HeartRateUtils(this).startHeartRateDetection();
		Intent inLoc = new Intent(this, LocationGpsService.class);
		inLoc.putExtra(ConstantGloble.EXTRATYPE,
				ConstantGloble.SOS_REQUEST_LOCATION);
		String path = null;
		try {
			path = Environment.getExternalStorageDirectory().getCanonicalPath()
					.toString()
					+ "/SosRecordingFiles/sosAudio.3gp";
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		inLoc.putExtra("SOS_RECORD_FILE", path);
		startService(inLoc);
	}
	
}
